package com.smart.community.region.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.property.service.DataScopeFeign;
import com.smart.community.region.dto.ZoneQueryDTO;
import com.smart.community.region.dto.ZoneInfoUpdateDTO;
import com.smart.community.region.entity.Zone;
import com.smart.community.region.entity.ZoneBuilding;
import com.smart.community.region.entity.ZoneDrawing;
import com.smart.community.region.mapper.ZoneMapper;
import com.smart.community.region.mapper.ZoneBuildingMapper;
import com.smart.community.region.mapper.ZoneDrawingMapper;
import com.smart.community.region.vo.ZoneDetailVO;
import com.smart.community.region.vo.ZoneBuildingVO;
import com.smart.community.region.vo.ZoneDrawingVO;
import com.smart.community.region.service.IZoneService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.List;
import java.util.stream.Collectors;
import java.util.ArrayList;
import com.smart.community.region.vo.ZoneWithBuildingsVO;

/**
 * 分区服务实现类
 *
 * @author Wu.Liang
 * @since 2025-01-30
 */
@Slf4j
@Service
public class ZoneServiceImpl extends ServiceImpl<ZoneMapper, Zone> implements IZoneService {

    @Autowired
    private ZoneBuildingMapper zoneBuildingMapper;
    
    @Autowired
    private ZoneDrawingMapper zoneDrawingMapper;

    @Autowired
    private DataScopeFeign dataScopeFeign;

    @Override
    public IPage<Zone> getZonePage(Page<Zone> page, ZoneQueryDTO queryDTO) throws Exception {
        log.info("分页查询分区列表，页码：{}，大小：{}，查询条件：{}", page.getCurrent(), page.getSize(), queryDTO);
        
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
        
        // 构建查询条件
        if (queryDTO != null) {
            // 分区名称模糊查询
            if (StringUtils.hasText(queryDTO.getZoneName())) {
                queryWrapper.like(Zone::getZoneName, queryDTO.getZoneName());
            }
            
            // 分区编码模糊查询
            if (StringUtils.hasText(queryDTO.getZoneCode())) {
                queryWrapper.like(Zone::getZoneCode, queryDTO.getZoneCode());
            }
            
            // 社区ID精确查询
            if (queryDTO.getCommunityId() != null) {
                queryWrapper.eq(Zone::getCommunityId, queryDTO.getCommunityId());
            }
            
            // 物业公司ID精确查询
            if (queryDTO.getPropertyCompanyId() != null) {
                queryWrapper.eq(Zone::getPropertyCompanyId, queryDTO.getPropertyCompanyId());
            }
            
            // 分区类型精确查询
            if (StringUtils.hasText(queryDTO.getZoneType())) {
                queryWrapper.eq(Zone::getZoneType, queryDTO.getZoneType());
            }
            
            // 状态精确查询
            if (queryDTO.getStatus() != null) {
                queryWrapper.eq(Zone::getStatus, queryDTO.getStatus());
            }
        }
        
        // 默认只查询启用状态的分区
        queryWrapper.eq(Zone::getStatus, SystemStatusEnum.ENABLED.getCode());
        
        // 应用数据权限过滤
        applyDataPermissionFilter(queryWrapper, currentUserId);
        
        // 按排序顺序和创建时间排序
        queryWrapper.orderByAsc(Zone::getSortOrder)
                   .orderByDesc(Zone::getCreateTime);
        
        return this.page(page, queryWrapper);
    }

    /**
     * 应用数据权限过滤
     * 
     * @param queryWrapper 查询条件包装器
     * @param currentUserId 当前用户ID
     */
    private void applyDataPermissionFilter(LambdaQueryWrapper<Zone> queryWrapper, Long currentUserId) {
        try {
            // 1. 检查超级管理员权限
            Boolean isSuperAdmin = dataScopeFeign.isUserSuperAdmin(currentUserId);
            if (Boolean.TRUE.equals(isSuperAdmin)) {
                log.debug("用户{}为超级管理员，不应用数据权限过滤", currentUserId);
                return;
            }
            
            // 2. 获取用户可访问的社区ID列表
            List<Long> communityIds = dataScopeFeign.getUserCommunityIds(currentUserId);
            if (communityIds.isEmpty()) {
                // 用户无权限访问任何社区数据，返回空结果
                log.debug("用户{}无权限访问任何社区数据", currentUserId);
                queryWrapper.eq(Zone::getId, -1L); // 使用不存在的ID确保返回空结果
                return;
            }
            
            // 3. 应用社区权限过滤
            queryWrapper.in(Zone::getCommunityId, communityIds);
            log.debug("用户{}数据权限过滤完成，可访问社区数量：{}", currentUserId, communityIds.size());
            
        } catch (Exception e) {
            log.error("应用数据权限过滤失败，用户ID：{}，错误：{}", currentUserId, e.getMessage());
            // 权限验证失败时，返回空结果，确保数据安全
            queryWrapper.eq(Zone::getId, -1L);
        }
    }

    @Override
    public List<ZoneWithBuildingsVO> getByCommunityId(Long communityId) {
        log.info("根据社区ID查询分区列表，社区ID: {}", communityId);
        
        LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Zone::getCommunityId, communityId)
                   .eq(Zone::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByDesc(Zone::getSortOrder);
        
        List<Zone> zones = this.list(queryWrapper);
        List<ZoneWithBuildingsVO> result = new ArrayList<>();
        
        // 为每个分区加载楼栋关联数据
        for (Zone zone : zones) {
            try {
                ZoneWithBuildingsVO zoneWithBuildings = new ZoneWithBuildingsVO();
                BeanUtils.copyProperties(zone, zoneWithBuildings);
                
                // 查询分区关联的楼栋
                LambdaQueryWrapper<ZoneBuilding> buildingWrapper = new LambdaQueryWrapper<>();
                buildingWrapper.eq(ZoneBuilding::getZoneId, zone.getId())
                              .eq(ZoneBuilding::getStatus, SystemStatusEnum.ENABLED.getCode());
                List<ZoneBuilding> zoneBuildings = zoneBuildingMapper.selectList(buildingWrapper);
                
                // 转换为楼栋VO列表
                List<ZoneBuildingVO> buildingVOs = zoneBuildings.stream().map(building -> {
                    ZoneBuildingVO buildingVO = new ZoneBuildingVO();
                    BeanUtils.copyProperties(building, buildingVO);
                    return buildingVO;
                }).collect(Collectors.toList());
                
                // 设置楼栋列表到分区对象中
                zoneWithBuildings.setBuildings(buildingVOs);
                
                result.add(zoneWithBuildings);
                
                log.debug("分区 {} 关联楼栋数量: {}", zone.getId(), buildingVOs.size());
            } catch (Exception e) {
                log.error("加载分区 {} 的楼栋关联数据失败", zone.getId(), e);
                ZoneWithBuildingsVO zoneWithBuildings = new ZoneWithBuildingsVO();
                BeanUtils.copyProperties(zone, zoneWithBuildings);
                zoneWithBuildings.setBuildings(new ArrayList<>());
                result.add(zoneWithBuildings);
            }
        }
        
        return result;
    }

    @Override
    public List<Zone> getByPropertyCompanyId(Long propertyCompanyId) {
        log.info("根据物业公司ID查询分区列表，物业公司ID: {}", propertyCompanyId);
        
        LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Zone::getPropertyCompanyId, propertyCompanyId)
                   .eq(Zone::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByAsc(Zone::getSortOrder);
        
        return this.list(queryWrapper);
    }

    @Override
    public boolean isZoneCodeExists(String zoneCode, Long communityId, Long excludeId) {
        log.info("检查分区编码是否存在，编码: {}, 社区ID: {}, 排除ID: {}", zoneCode, communityId, excludeId);
        
        LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Zone::getZoneCode, zoneCode)
                   .eq(Zone::getCommunityId, communityId)
                   .eq(Zone::getStatus, SystemStatusEnum.ENABLED.getCode());
        
        if (excludeId != null) {
            queryWrapper.ne(Zone::getId, excludeId);
        }
        
        return this.count(queryWrapper) > 0;
    }

    @Override
    public boolean saveBatchZones(List<Zone> zones) {
        log.info("批量保存分区，数量: {}", zones.size());
        
        if (zones == null || zones.isEmpty()) {
            return true;
        }
        
        return this.saveBatch(zones);
    }

    @Override
    public boolean updateBatchZones(List<Zone> zones) {
        log.info("批量更新分区，数量: {}", zones.size());
        
        if (zones == null || zones.isEmpty()) {
            return true;
        }
        
        return this.updateBatchById(zones);
    }

    @Override
    public ZoneDetailVO getZoneDetail(Long id) throws Exception {
        log.info("查询分区详情，分区ID: {}", id);
        
        // 查询分区基本信息
        Zone zone = this.getById(id);
        if (zone == null) {
            log.warn("分区不存在，分区ID: {}", id);
            return null;
        }
        
        // 数据权限验证
        validateZonePermission(zone);
        
        // 转换为VO
        ZoneDetailVO zoneDetailVO = new ZoneDetailVO();
        BeanUtils.copyProperties(zone, zoneDetailVO);
        
        // 查询分区关联的楼栋
        LambdaQueryWrapper<ZoneBuilding> buildingWrapper = new LambdaQueryWrapper<>();
        buildingWrapper.eq(ZoneBuilding::getZoneId, id)
                      .eq(ZoneBuilding::getStatus, SystemStatusEnum.ENABLED.getCode());
        List<ZoneBuilding> zoneBuildings = zoneBuildingMapper.selectList(buildingWrapper);
        
        // 转换为楼栋VO
        List<ZoneBuildingVO> buildingVOs = zoneBuildings.stream().map(building -> {
            ZoneBuildingVO buildingVO = new ZoneBuildingVO();
            BeanUtils.copyProperties(building, buildingVO);
            return buildingVO;
        }).collect(Collectors.toList());
        
        zoneDetailVO.setBuildings(buildingVOs);
        
        // 查询绘图数据
        LambdaQueryWrapper<ZoneDrawing> drawingWrapper = new LambdaQueryWrapper<>();
        drawingWrapper.eq(ZoneDrawing::getCommunityId, zone.getCommunityId())
                     .eq(ZoneDrawing::getIsCurrent, true);
        ZoneDrawing zoneDrawing = zoneDrawingMapper.selectOne(drawingWrapper);
        
        if (zoneDrawing != null) {
            ZoneDrawingVO drawingVO = new ZoneDrawingVO();
            BeanUtils.copyProperties(zoneDrawing, drawingVO);
            zoneDetailVO.setDrawingData(drawingVO);
        }
        
        log.info("查询分区详情成功，分区ID: {}", id);
        return zoneDetailVO;
    }

    @Override
    public boolean updateZoneInfo(Long id, ZoneInfoUpdateDTO dto, Long currentUserId) throws Exception {
        log.info("更新分区基本信息，分区ID: {}, 分区名称: {}", id, dto.getZoneName());
        
        // 查询分区信息
        Zone zone = this.getById(id);
        if (zone == null) {
            throw new RuntimeException("分区不存在");
        }
        
        // 数据权限验证
        validateZonePermission(zone);
        
        // 更新分区信息
        BeanUtils.copyProperties(dto, zone);
        zone.setUpdateBy(currentUserId);
        
        return this.updateById(zone);
    }

    /**
     * 验证分区操作权限
     * 
     * @param zone 分区信息
     */
    private void validateZonePermission(Zone zone) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        try {
            // 1. 检查超级管理员权限
            Boolean isSuperAdmin = dataScopeFeign.isUserSuperAdmin(currentUserId);
            if (Boolean.TRUE.equals(isSuperAdmin)) {
                log.debug("用户{}为超级管理员，拥有所有权限", currentUserId);
                return;
            }
            
            // 2. 验证社区权限
            Boolean hasCommunityPermission = dataScopeFeign.hasCommunityPermission(currentUserId, zone.getCommunityId());
            if (!Boolean.TRUE.equals(hasCommunityPermission)) {
                log.warn("用户{}无权限操作社区{}的分区", currentUserId, zone.getCommunityId());
                throw new RuntimeException("无权限操作该分区");
            }
            
            log.debug("用户{}分区权限验证通过，分区ID: {}", currentUserId, zone.getId());
        } catch (RuntimeException e) {
            // 业务异常直接抛出
            throw e;
        } catch (Exception e) {
            log.error("分区权限验证失败，用户ID: {}, 分区ID: {}, 错误: {}", currentUserId, zone.getId(), e.getMessage());
            // 权限验证失败时，默认拒绝访问，确保安全性
            throw new RuntimeException("权限验证失败，请稍后重试");
        }
    }
}
